#include "syntax_tree.h"
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <malloc.h>

syntax_t syntax_t_new(int type,int chno,...){
	va_list ap;
	syntax_t tree;
	int i;
	if(chno<=0)
		return NULL;
	if((tree=(syntax_t)malloc(sizeof(struct syntax_tree)))==NULL){
		printf ("out of mem\n");
		return NULL;
	}
	tree->type=SYN_OP;
	tree->op.type=type;
	tree->op.chno=chno;
	if((tree->op.children=(syntax_t*)malloc(sizeof(syntax_t)*chno))==NULL){
		printf ("out of mem\n");
		free(tree);
		return NULL;
	}
	va_start(ap,chno);
	for(i=0;i<chno;i++)
		tree->op.children[i]=va_arg(ap,syntax_t);
	va_end(ap);
	return  tree;
}
syntax_t syntax_t_get(syntax_t tree,int no)
{
	if(tree->type!=SYN_OP)
		return NULL;
	if(no<tree->op.chno && no>0)
		return tree->op.children[no];
	return NULL;
}

syntax_t syntax_t_const(int value)
{
	syntax_t tree;
	if((tree=(syntax_t)malloc(sizeof(struct syntax_tree)))==NULL){
		printf ("out of mem\n");
		return NULL;
	}
	tree->type=SYN_CONST;
	tree->con.value=value;
	return tree;
}
syntax_t syntax_t_id(const char* name)
{
	syntax_t tree;
	if((tree=(syntax_t)malloc(sizeof(struct syntax_tree)))==NULL){
		printf ("out of mem\n");
		return NULL;
	}
	tree->type=SYN_ID;
	tree->id.name=strdup(name);
}
void free_id(syntax_t t)
{
	if(t->type==SYN_ID){
		free(t->id.name);
		free(t);
	}
}
void free_const(syntax_t t)
{
	if(t->type==SYN_CONST)
		free(t);
}
void free_op(syntax_t t)
{
	int i;
	if(t->type==SYN_OP){
		for (i=0; i < t->op.chno; ++i)
			{	
				syntax_t_delete(t->op.children[i]);			
			}
		free(t);
	}
}
void print_op(syntax_t t)
{
	int i;
	if(t->type==SYN_OP){
		printf("op is %c,it has %d child\n",t->op.type,t->op.chno);
		for (i=0; i < t->op.chno; ++i)
			{	
				syntax_t_print(t->op.children[i]);			
			}
	}
}
void print_const(syntax_t t)
{
	if(t->type==SYN_CONST){
		printf ("it is const=%d\n",t->con.value);
	}
}
void print_id(syntax_t t)
{
	if(t->type==SYN_ID){
		printf ("it is id,name is %s\n",t->id.name);
	}
}
struct syn_type_func{
	SYN_TYPE type;
	void (*free)(syntax_t);
	void (*print)(syntax_t);
}syn_type_funcs[]={
	{SYN_ID,free_id,print_id},
	{SYN_CONST,free_const,print_const},
	{SYN_OP,free_op,print_op},
};

void syntax_t_delete(syntax_t t)
{
	int i;
	if(t->type<=SYN_MIN_TYPE && t->type>=SYN_MAX_TYPE)
		printf ("free err syntax_t\n");
	for (i = 0; i < sizeof(syn_type_funcs); ++i)
		{
			if(t->type==syn_type_funcs[i].type)
				syn_type_funcs[i].free(t);
		}
}
void syntax_t_print(syntax_t t)
{
	int i;
	if(t->type<=SYN_MIN_TYPE && t->type>=SYN_MAX_TYPE)
		printf ("free err print syntax\n");
	for (i = 0; i < sizeof(syn_type_funcs); ++i)
		{
			if(t->type==syn_type_funcs[i].type)
				syn_type_funcs[i].print(t);
		}
}
